package com.study.money;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.study.util.FileUtil;
import com.study.util.HttpUtils;
import org.apache.commons.lang3.tuple.Pair;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * TODO
 *
 * @author wanghuilong
 * @version 1.0
 * @date 2022/2/9 12:53 下午
 */
public class Test1 {

    private static String token = "cb910d761e14e02360bb222271de38ff";

    private static String queryUrl = "http://api.waizaowang.com/doc/getFundNav?&export=1&fields=all&";

    private static String dataPath = "/Users/wanghuilong/IdeaProjects/lazy/src/main/java/com/study/money/data/";

    private static String reportPath = "/Users/wanghuilong/IdeaProjects/lazy/src/main/java/com/study/money/";

    public static Map<String, String> jijinMap = new LinkedHashMap<>();


    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");


    //时间类型 TimeTypeEnum.TWO_WEEK,TimeTypeEnum.ONE_MONTH,TimeTypeEnum.THREE_MONTH,TimeTypeEnum.SIX_MONTH
    //TimeTypeEnum.ONE_YEAR
    public static List<TimeTypeEnum> timeTypeEnumList = Lists.newArrayList(
            TimeTypeEnum.TWO_WEEK,TimeTypeEnum.ONE_MONTH,TimeTypeEnum.THREE_MONTH,TimeTypeEnum.SIX_MONTH);

    public static Boolean saveFile = Boolean.FALSE;

    static {
        jijinMap.put("013275", "富国中证煤炭指数C");
        jijinMap.put("008280", "国泰中证煤炭ETF联接C");
        jijinMap.put("004857", "广发中证全指建筑材料指数C");
        jijinMap.put("013035", "国富军工中证指数C");
        jijinMap.put("010990", "南方有色金属联接C");
        jijinMap.put("010990", "南方有色金属联接C");
        jijinMap.put("004598", "南方银行联接C");
        jijinMap.put("012042", "鹏华银行C");
        jijinMap.put("012402", "天弘中证医药指数增强C");
        jijinMap.put("003096", "中欧医疗健康混合C");
        jijinMap.put("011854", "招商中证消费龙头指数增强C");
        jijinMap.put("008888", "华夏国证半导体芯片ETF联接C");
        jijinMap.put("011513", "天弘中证新能源汽车指数发起式C");
        jijinMap.put("012863", "汇添富中证电池主题指数发起式C");
        jijinMap.put("006503", "财通继承电路产业股票C");
        jijinMap.put("012895", "天弘中证科创创业50指数C");
        jijinMap.put("005413", "金信民长混合C");
        jijinMap.put("011103", "天弘中证光伏C");
        jijinMap.put("011967", "招商中证光伏产业指数C");
        jijinMap.put("013606", "华夏中证内地低碳经济主题ETF发起式联接C");
    }
    /*
    * 2月9日
    *

    30日
    南方有色金属联接C-均值:1.2635
    南方银行联接C-均值:1.3135
    鹏华银行C-均值:0.9857
    天弘中证医药指数增强C-均值:0.9323
    中欧医疗健康混合C-均值:2.7009
    招商中证消费龙头指数增强C-均值:0.9619
    华夏国证半导体芯片ETF联接C-均值:1.2980
    天弘中证新能源汽车指数发起式C-均值:1.3604
    汇添富中证电池主题指数发起式C-均值:0.9382
    财通继承电路产业股票C-均值:1.8896
    天弘中证科创创业50指数C-均值:0.8242
    金信民长混合C-均值:1.8008
    天弘中证光伏C-均值:1.2248
    招商中证光伏产业指数C-均值:0.9662
    华夏中证内地低碳经济主题ETF发起式联接C-均值:0.8926

    360日
    南方有色金属联接C-均值:1.2757
    南方银行联接C-均值:1.3194
    鹏华银行C-均值:0.9826
    天弘中证医药指数增强C-均值:1.0093
    中欧医疗健康混合C-均值:3.4412
    招商中证消费龙头指数增强C-均值:0.9798
    华夏国证半导体芯片ETF联接C-均值:1.3016
    天弘中证新能源汽车指数发起式C-均值:1.4081
    汇添富中证电池主题指数发起式C-均值:1.0409
    财通继承电路产业股票C-均值:2.0643
    天弘中证科创创业50指数C-均值:0.9164
    金信民长混合C-均值:1.8248
    天弘中证光伏C-均值:1.1754
    招商中证光伏产业指数C-均值:1.0576
    华夏中证内地低碳经济主题ETF发起式联接C-均值:0.9698

    2.9
    投资计划：
    1、超出30日均线 1.6%
    南方银行联接C
    买入200，损失超过3%，100%撤回，最大时间是10个交易日
    止盈：3%

    2.11
    投资计划：
    1、超出30日均线8%，90日均线7%，且突破30和90日最高价
    富国中证煤炭指数C
    买入一个头寸： 600 ，损失超过3%，退出，50%撤回，损失超过5%，退出，100%撤回
    止盈:5%

    2、超出30日均线 3.9% 90日 5.9%
    南方银行联接C
    买入400，损失超过3%，100%撤回，最大时间是10个交易日
    止盈：3%

    3、
    国泰中证煤炭ETF联接C
    买入0.5个头寸： 300 ，损失超过3%，退出，50%撤回，损失超过5%，退出，100%撤回
    止盈:5%

    2.14
    国泰中证煤炭ETF联接C 维持突破30日和90日均线，距离90日最大值有较大距离 持续时间 1个月
    买入0.2个头寸： 120 ，损失超过3%，退出，50%撤回，损失超过5%，退出，100%撤回
    *
    2.16
    南方有色金属联接C 突破30和90日均线，距离30和90日最大值有距离 0.03左右：2.2% 跌回最近均线90日：1.2878 2.2%
    买入0.5个头寸： 300 ，损失超过3%，退出，50%撤回，损失超过5%，退出，100%撤回

    2.17 (未执行)
    天弘中证新能源汽车指数发起式C 突破30日均线 2%，距离90日均线：1.8%
    买入0.5个头寸： 300

    金信民长混合C 突破30日均线 3.9%  距离90日均线：0.4%
    买入0.5个头寸： 300
    *
    2.18
    天弘中证新能源汽车指数发起式C 突破30日均线 2%，距离90日均线：1.8%
    买入0.5个头寸： 300

    南方有色金属联接C
    买入0.5个头寸： 300

    广发中证全指建筑材料指数C
    买入0.5个头寸： 300

    金信民长混合C
    买入0.8个头寸： 480

    国泰中证煤炭ETF联接C
    买入0.5个头寸： 300

    南方银行联接C
    买入0.25个头寸： 150

    2.22
    天弘中证光伏C 突破30均值，距离90日均值很远
    买入0.5个头寸： 300
    招商中证光伏产业指数C 突破30均值，距离90日均值很远
    买入0.5个头寸： 300

    关注 广发中证全指建筑材料指数C 跌破 30日均线

    其他补充 100

    2.23

    关注 广发中证全指建筑材料指数C 跌破 30日均线：1.5021
    关注 南方银行联接C 跌破 30日均线：1.3324

    略微突破30日均线，距离90日均线较远
    天弘中证医药指数增强C 150
    中欧医疗健康混合C 150
    华夏中证内地低碳经济主题ETF发起式联接C 150

    较高突破30日均线，距离90日均线较远
    国富军工中证指数C  300
    华夏国证半导体芯片ETF联接C 300
    招商中证光伏产业指数C 200
    天弘中证光伏C 300
    汇添富中证电池主题指数发起式C 300
    天弘中证新能源汽车指数发起式C 300
    财通继承电路产业股票C 300

    2.24

    在继续突破的时候追加投资，而不是洒水式补仓
    *

    2.25

    国泰中证煤炭ETF联接C 逼近低于90日均线
    赎回 50%

    略微突破30日均线，距离90日均线较远
    天弘中证科创创业50指数C 300
    国富军工中证指数C  100
    华夏国证半导体芯片ETF联接C 100
    招商中证光伏产业指数C 100
    天弘中证光伏C 100
    汇添富中证电池主题指数发起式C 100
    天弘中证新能源汽车指数发起式C 100
    财通继承电路产业股票C 100
    天弘中证医药指数增强C 150
    中欧医疗健康混合C 150
    华夏中证内地低碳经济主题ETF发起式联接C 150

    2.28
    国富军工中证指数C
    买入0.5个头寸： 300

    南方有色金属联接C
    买入0.5个头寸： 300

    其他补充 100：
    华夏国证半导体芯片ETF联接C
    天弘中证新能源汽车指数发起式C

    其他补充 150：
    华夏中证内地低碳经济主题ETF发起式联接C
    招商中证光伏产业指数C
    天弘中证光伏C
    金信民长混合C
    * */

    public static void main(String[] args) {
        Date date = new Date();
        for (TimeTypeEnum timeTypeEnum : timeTypeEnumList) {
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> entry : jijinMap.entrySet()) {
                String code = entry.getKey();
                String name = entry.getValue();
                //查询估值
                BigDecimal estimateValue = getEstimateValue(code);
                sb.append("----- " + name + " 估值: " + estimateValue).append("\n");
                //最大值
                BigDecimal maxValue = new BigDecimal(0);
                //最小值
                BigDecimal minValue = new BigDecimal(1000000000);
                Pair<String, String> startEndTime = getStartEndTime(date, timeTypeEnum);
                sb.append(startEndTime.getLeft() + " ~ " + startEndTime.getRight() + " " + timeTypeEnum.name() + " :").append("\n");
                String queryUrl = getQueryUrl(code, startEndTime.getLeft(), startEndTime.getRight());
                String s = HttpUtils.get(queryUrl);
                System.out.println(s);
                if (Boolean.TRUE.equals(saveFile)) {
                    FileUtil.writeToFileOverWrite(s, dataPath + code + ".json");
                }
                JSONObject jsonObject = JSONObject.parseObject(s);
                JSONArray data = jsonObject.getJSONArray("data");
                if (data.size() == 0) {
                    System.out.println("无交易日");
                    continue;
                }
                BigDecimal sum = new BigDecimal(0);
                for (int i = 0; i < data.size(); i++) {
                    JSONObject dataObj = data.getJSONObject(i);
                    String nav = dataObj.getString("nav");
                    BigDecimal navValue = new BigDecimal(nav);
                    sum = sum.add(navValue);
                    if (maxValue.compareTo(navValue) == -1) {
                        maxValue = navValue;
                    }
                    if (minValue.compareTo(navValue) == 1) {
                        minValue = navValue;
                    }
                }
                //计算均值
                BigDecimal meanValue = sum.divide(new BigDecimal(data.size()), 2);
                //计算估值与均值的比例
                BigDecimal estimateMeanValueRate = estimateValue.subtract(meanValue).divide(meanValue, 3);
                sb.append("均值：" + meanValue).append("\n");
                sb.append("最大值：" + maxValue).append("\n");
                sb.append("最小值：" + minValue).append("\n");
                sb.append("估值与均值的比例：" + estimateMeanValueRate).append("\n");
            }
            String fileName = reportPath + timeTypeEnum.name() + ".txt";
            FileUtil.writeToFileOverWrite(sb.toString(), fileName);
        }
    }

    public static JSONArray getData(String code, Date date, TimeTypeEnum timeTypeEnum) {
        Pair<String, String> startEndTime = getStartEndTime(date, timeTypeEnum);
        String queryUrl = getQueryUrl(code, startEndTime.getLeft(), startEndTime.getRight());
        String s = HttpUtils.get(queryUrl);
        JSONObject jsonObject = JSONObject.parseObject(s);
        return jsonObject.getJSONArray("data");
    }

    /**
     * 查询估值
     *
     * @return
     */
    private static BigDecimal getEstimateValue(String code) {
        String queryEstimateValueUrl = getQueryEstimateValueUrl(code);
        String s = HttpUtils.get(queryEstimateValueUrl);
        s = s.replace("jsonpgz(", "").replace(");", "");
        JSONObject jsonObject = JSONObject.parseObject(s);
        String gsz = jsonObject.getString("gsz");
        return new BigDecimal(gsz);
    }

    /**
     * 查询实时估值
     *
     * @param code
     * @return
     */
    public static String getQueryEstimateValueUrl(String code) {
        long time = System.currentTimeMillis();
        return new StringBuilder("https://fundgz.1234567.com.cn/js/").append(code).append(".js?rt=").append(time).toString();
    }


    /**
     * 查询历史净值
     *
     * @param code
     * @param startDate
     * @param endDate
     * @return
     */
    public static String getQueryUrl(String code, String startDate, String endDate) {
        return new StringBuilder(queryUrl).append("code=").append(code).append("&startDate=").append(startDate)
                .append("&endDate=").append(endDate).append("&token=").append(token).toString();
    }




    public static Pair<String, String> getStartEndTime(Date date, TimeTypeEnum timeTypeEnum) {
        String endDate = dateFormat.format(date);

        long time = date.getTime() - timeTypeEnum.getLastDay() * 24 * 3600000L;
        Date startTime = new Date(time);
        String startDate = dateFormat.format(startTime);

        return Pair.of(startDate, endDate);
    }

    static enum TimeTypeEnum {

        ONE_WEEK(7),

        TWO_WEEK(14),

        DAY25(25),

        ONE_MONTH(30),

        THREE_MONTH(90),

        SIX_MONTH(180),

        ONE_YEAR(365),

        TWO_YEAR(730),

        THREE_YEAR(1095),

        TEN_YEAR(3650),
        ;

        private Integer lastDay;

        TimeTypeEnum(Integer lastDay) {
            this.lastDay = lastDay;
        }

        public Integer getLastDay() {
            return lastDay;
        }
    }
}
